/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.dao;

import org.ipti.br.tag.entity.*;
import java.io.Serializable;
import java.util.Calendar;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.*;


/**
 *
 * @author FelipeMSX
 */
@Stateless
public class WeightAndHeightFacade extends AbstractFacade<WeightAndHeight> implements Serializable{
    
    @PersistenceContext(unitName = "TAG2PU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public WeightAndHeightFacade() {
        super(WeightAndHeight.class);
    }
       
    public List<WeightAndHeight> findAllWeightAndHeight(Unity unity, Campaign campaign){

        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<WeightAndHeight> cq = cb.createQuery(WeightAndHeight.class);
        Root<WeightAndHeight> root = cq.from(WeightAndHeight.class);
        Join<WeightAndHeight,Human> join1 = root.join(WeightAndHeight_.human);
        Predicate p1 = cb.equal( root.join( WeightAndHeight_.human ).join(Human_.actors).join(Actor_.unity).get(Unity_.id), unity.getId());
        Predicate p2 = cb.equal( root.join( WeightAndHeight_.campaign ).get(Campaign_.id), campaign.getId());
        cq.select(join1.getParent()).where( cb.and( p1,p2) );

        try{
            return getEntityManager().createQuery(cq).getResultList();
        }catch(NoResultException e){
            e.printStackTrace();
            return null;
        }
    }
    
    public List<WeightAndHeight> modifiedPerfFreqBetweenDate(Calendar initialDate, Calendar finalDate, Long serialNumber) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<WeightAndHeight> cq = cb.createQuery(WeightAndHeight.class);
        Root<WeightAndHeight> from = cq.from(WeightAndHeight.class);
        Predicate predicate1 = cb.notEqual(from.get(WeightAndHeight_.serialNumber), serialNumber);
        Predicate predicate2 = cb.greaterThanOrEqualTo(from.get(WeightAndHeight_.lastModified), initialDate);
        Predicate predicate3 = cb.lessThan(from.get(WeightAndHeight_.lastModified), finalDate);
        cq.where(cb.and(predicate1, predicate2, predicate3));

        return getEntityManager().createQuery(cq).getResultList();
    }
    
//    public Object[] getLastMeasure(Human human) {
//        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
//        CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
//        Root<WeightAndHeight> rt = cq.from(WeightAndHeight.class);
//        
//        cq.multiselect(cb.least(rt.get(WeightAndHeight_.collectionDate)),rt);
//        
//        cq.where(cb.equal(rt.get(WeightAndHeight_.human).get(Human_.id), human.getId()));
//
//        cq.groupBy(rt.get(WeightAndHeight_.human).get(Human_.id));
//        
//        try {
//            return getEntityManager().createQuery(cq).getSingleResult();
//        } catch (NoResultException nre) {
//            return null;
//        }
//    }
    
    public WeightAndHeight getLastMeasure(Human human) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<WeightAndHeight> cq = cb.createQuery(WeightAndHeight.class);
        Root<WeightAndHeight> rt = cq.from(WeightAndHeight.class);
        
        Subquery<Calendar> subQ = cq.subquery(Calendar.class);
        Root<WeightAndHeight> subRt = subQ.from(WeightAndHeight.class);
        subQ.select(cb.greatest(subRt.get(WeightAndHeight_.collectionDate)));
        subQ.where(cb.equal(subRt.get(WeightAndHeight_.human).get(Human_.id), rt.get(WeightAndHeight_.human).get(Human_.id)));
        
        cq.where(cb.equal(rt.get(WeightAndHeight_.human).get(Human_.id), human.getId()));

        cq.distinct(true);
        try {
            return getEntityManager().createQuery(cq).getSingleResult();
        } catch (NoResultException nre) {
            return null;
        }
    }
    
//    public WeightAndHeight getLastMeasure(Human human) {
//        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
//        CriteriaQuery<WeightAndHeight> cq = cb.createQuery(WeightAndHeight.class);
//        Root<WeightAndHeight> rt = cq.from(WeightAndHeight.class);
//        
//        Predicate p1 = cb.equal(rt.get(WeightAndHeight_.human).get(Human_.id), human.getId());
//        Predicate p2 = cb.equal(rt.get(WeightAndHeight_.collectionDate), cb.greatest(rt.get(WeightAndHeight_.collectionDate)));
//        cq.where(p1,p2);
//        
//        try {
//            return getEntityManager().createQuery(cq).getSingleResult();
//        } catch (NoResultException nre) {
//            return null;
//        }
//    }
}
